def lianxi(hlir16,generated_code):
    global file_indentation_level
    global file_sugar_style
    file_indentation_level = 0

    # The last element is the innermost (current) style.
    file_sugar_style = ['line_comment']


    def add_code(line, lineno = None, file = "compiler/backend/dataplane.c.py"):
        global file_indentation_level
        global file_sugar_style
        global generated_code

        line_ends = {
            "line_comment": "\n",
            "inline_comment": "",
        }

        stripped_line = line.strip()
        no_sugar_on_line = stripped_line.startswith('//') or stripped_line.startswith('# ') or stripped_line == ""

        indent = '    ' * file_indentation_level
        return indent + line + sugar(no_sugar_on_line, file, lineno) + line_ends[file_sugar_style[-1]]


    class SugarStyle():
        def __init__(self, sugar):
            global file_sugar_style
            file_sugar_style.append(sugar)

        def __enter__(self):
            global file_sugar_style
            return file_sugar_style[-1]

        def __exit__(self, type, value, traceback):
            global file_sugar_style
            file_sugar_style.pop()


    def sugar(no_sugar_on_line, file, lineno):
        if no_sugar_on_line or file is None or lineno is None:
            return ""

        import re
        global file_sugar_style

        if file_sugar_style[-1] == 'line_comment':
            if no_sugar_on_line:
                return ""
            return " // {}:{}".format(file, lineno)
        if file_sugar_style[-1] == 'inline_comment':
            if file == "../compiler/backend/dataplane.c.py":
                return " /* {} */ {}".format(lineno)
            return " /* {}:{} */".format(file, lineno)
        return line


    generated_code += "// Autogenerated file (from compiler/backend/dataplane.c.py via ../compiler/backend/dataplane.c.py), do not modify directly.\n"
    generated_code += "// Generator: PPK\n"
    generated_code += "\n"

    # Copyright 2016 Eotvos Lorand University, Budapest, Hungary ## compiler/backend/dataplane.c.py:2
    #  ## compiler/backend/dataplane.c.py:3
    # Licensed under the Apache License, Version 2.0 (the "License"); ## compiler/backend/dataplane.c.py:4
    # you may not use this file except in compliance with the License. ## compiler/backend/dataplane.c.py:5
    # You may obtain a copy of the License at ## compiler/backend/dataplane.c.py:6
    #  ## compiler/backend/dataplane.c.py:7
    #     http://www.apache.org/licenses/LICENSE-2.0 ## compiler/backend/dataplane.c.py:8
    #  ## compiler/backend/dataplane.c.py:9
    # Unless required by applicable law or agreed to in writing, software ## compiler/backend/dataplane.c.py:10
    # distributed under the License is distributed on an "AS IS" BASIS, ## compiler/backend/dataplane.c.py:11
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ## compiler/backend/dataplane.c.py:12
    # See the License for the specific language governing permissions and ## compiler/backend/dataplane.c.py:13
    # limitations under the License. ## compiler/backend/dataplane.c.py:14

    generated_code += add_code("")
    from utils.codegen import format_declaration, format_statement, format_expr, format_type, type_env ## compiler/backend/dataplane.c.py:16
    from utils.misc import addError, addWarning ## compiler/backend/dataplane.c.py:17

    generated_code += add_code("")
    generated_code += add_code(" #include <stdlib.h>", 18)
    generated_code += add_code(" #include <string.h>", 19)
    generated_code += add_code(" #include <stdbool.h>", 20)
    generated_code += add_code(" #include \"dpdk_lib.h\"", 21)
    generated_code += add_code(" #include \"actions.h\"", 22)
    generated_code += add_code(" #include \"backend.h\"", 23)
    generated_code += add_code(" #include \"util.h\"", 24)
    generated_code += add_code(" #include \"util_packet.h\"", 25)
    generated_code += add_code(" #include \"tables.h\"", 26)

    generated_code += add_code("")
    generated_code += add_code(" uint8_t* emit_addr;", 28)
    generated_code += add_code(" uint32_t ingress_pkt_len;", 29)

    generated_code += add_code("")
    generated_code += add_code(" extern ctrl_plane_backend bg;", 31)
    generated_code += add_code(" extern char* action_names[];", 32)

    generated_code += add_code("")
    generated_code += add_code(" extern void parse_packet(STDPARAMS);", 34)
    generated_code += add_code(" extern void increase_counter(int counterid, int index);", 35)
    generated_code += add_code(" extern void set_handle_packet_metadata(packet_descriptor_t* pd, uint32_t portid);", 36)

    generated_code += add_code("")
    # note: 0 is for the special case where there are no tables ## compiler/backend/dataplane.c.py:39
    max_key_length = max([t.key_length_bytes for t in hlir16.tables if hasattr(t, 'key')] + [0]) ## compiler/backend/dataplane.c.py:40
    generated_code += add_code(' uint8_t reverse_buffer[{}];'.format(max_key_length), 40)

    generated_code += add_code("")
    ################################################################################ ## compiler/backend/dataplane.c.py:43

    generated_code += add_code("")
    packet_name = hlir16.p4_main.type.baseType.type_ref.name ## compiler/backend/dataplane.c.py:45
    pipeline_elements = hlir16.p4_main.arguments ## compiler/backend/dataplane.c.py:46

    generated_code += add_code("")
    if hlir16.p4_model == 'V1Switch': ## compiler/backend/dataplane.c.py:48
        p4_ctls = [ctl for pe in pipeline_elements for ctl in [hlir16.objects.get(pe.expression.type.name, 'P4Control')] if ctl is not None] ## compiler/backend/dataplane.c.py:49
    elif hlir16.p4_model == 'PSA_Switch': ## compiler/backend/dataplane.c.py:50
        parsers_controls = [hlir16.objects.get(arg2.expression.type.name, ['P4Control', 'P4Parser']) ## compiler/backend/dataplane.c.py:51
            for arg in hlir16.p4_main.arguments ## compiler/backend/dataplane.c.py:52
            if arg.expression.node_type == "PathExpression" # ignoring PacketReplicationEngine and BufferingQueueingEngine for now ## compiler/backend/dataplane.c.py:53
            for arg2 in arg.expression.ref.arguments ## compiler/backend/dataplane.c.py:54
            ] ## compiler/backend/dataplane.c.py:55
        p4_ctls = [pc for pc in parsers_controls if pc.node_type == 'P4Control'] ## compiler/backend/dataplane.c.py:57
    else: ## compiler/backend/dataplane.c.py:58
        # if the P4 model is unknown, it would already be detected ## compiler/backend/dataplane.c.py:59
        pass ## compiler/backend/dataplane.c.py:60
    generated_code += add_code(" struct apply_result_s {", 62)
    generated_code += add_code("     bool hit;", 63)
    generated_code += add_code("     enum actions action_run;", 64)
    generated_code += add_code(" };", 65)

    generated_code += add_code("")
    for ctl in p4_ctls: ## compiler/backend/dataplane.c.py:68
        generated_code += add_code(' void control_{}(STDPARAMS);'.format(ctl.name), 68)
        for t in ctl.controlLocals['P4Table']: ## compiler/backend/dataplane.c.py:70
            generated_code += add_code(' struct apply_result_s {}_apply(STDPARAMS);'.format(t.name), 70)
    ################################################################################ ## compiler/backend/dataplane.c.py:73

    generated_code += add_code("")
    # TODO move this to HAL ## compiler/backend/dataplane.c.py:75
    def match_type_order(t): ## compiler/backend/dataplane.c.py:76
        if t == 'EXACT':   return 0 ## compiler/backend/dataplane.c.py:77
        if t == 'LPM':     return 1 ## compiler/backend/dataplane.c.py:78
        if t == 'TERNARY': return 2 ## compiler/backend/dataplane.c.py:79
        else:              return 3 ## compiler/backend/dataplane.c.py:80
    ################################################################################ ## compiler/backend/dataplane.c.py:82
    # Table key calculation ## compiler/backend/dataplane.c.py:83

    generated_code += add_code("")
    for table in hlir16.tables: ## compiler/backend/dataplane.c.py:85
        if not hasattr(table, 'key'): ## compiler/backend/dataplane.c.py:86
            continue ## compiler/backend/dataplane.c.py:87
        generated_code += add_code(' void table_{}_key(packet_descriptor_t* pd, uint8_t* key) {{'.format(table.name), 88)
        sortedfields = sorted(table.key.keyElements, key=lambda k: match_type_order(k.match_type)) ## compiler/backend/dataplane.c.py:90
        #TODO variable length fields ## compiler/backend/dataplane.c.py:91
        #TODO field masks ## compiler/backend/dataplane.c.py:92
        print(sortedfields)
        for f in sortedfields: ## compiler/backend/dataplane.c.py:93
            print(f)
            if f.get_attr('width') is None: ## compiler/backend/dataplane.c.py:94
                # addError('Computing key for table', 'the width attribute of field {} is missing'.format(f.name)) ## compiler/backend/dataplane.c.py:95
                continue ## compiler/backend/dataplane.c.py:96
            hi_name = "all_metadatas" if f.header_name in ['meta', 'standard_metadata'] else f.header.name ## compiler/backend/dataplane.c.py:98
            href = "header_instance_{}".format(hi_name) ## compiler/backend/dataplane.c.py:99
            # fref = "field_{}_{}".format(f.header_name, f.field_name) ## compiler/backend/dataplane.c.py:100
            fref = "field_{}_{}".format(f.header.type.type_ref.name, f.field_name) ## compiler/backend/dataplane.c.py:101
            if f.width <= 32: ## compiler/backend/dataplane.c.py:103
                generated_code += add_code(" #ifdef PPK_DEBUG", 103)
                generated_code += add_code('     if (unlikely(pd->headers[header_instance_{}].pointer == NULL)) {{'.format(hi_name), 104)
                generated_code += add_code('         debug(" " T4LIT(!!!!,error) " " T4LIT(Lookup on invalid header,error) " " T4LIT({},header) "." T4LIT({},field) "\\n");'.format(hi_name, f.field_name), 105)
                generated_code += add_code("     }", 106)
                generated_code += add_code(" #endif", 107)
                generated_code += add_code(' EXTRACT_INT32_BITS_PACKET(pd, {}, {}, *(uint32_t*)key)'.format(href, fref), 108)
                generated_code += add_code(" key += sizeof(uint32_t);", 109)
            elif f.width > 32 and f.width % 8 == 0: ## compiler/backend/dataplane.c.py:111
                byte_width = (f.width+7)/8 ## compiler/backend/dataplane.c.py:112
                generated_code += add_code(' EXTRACT_BYTEBUF_PACKET(pd, {}, {}, key)'.format(href, fref), 112)
                generated_code += add_code(' key += {};'.format(byte_width), 113)
            else: ## compiler/backend/dataplane.c.py:115
                addWarning("table key calculation", "Skipping unsupported field {} ({} bits): it is over 32 bits long and not byte aligned".format(f.id, f.width)) ## compiler/backend/dataplane.c.py:116
        if table.match_type == "LPM": ## compiler/backend/dataplane.c.py:118
            generated_code += add_code(' key -= {};'.format(table.key_length_bytes), 118)
            generated_code += add_code(" int c, d;", 119)
            generated_code += add_code(' for(c = {}, d = 0; c >= 0; c--, d++) *(reverse_buffer+d) = *(key+c);'.format(table.key_length_bytes-1), 120)
            generated_code += add_code(' for(c = 0; c < {}; c++) *(key+c) = *(reverse_buffer+c);'.format(table.key_length_bytes), 121)
        generated_code += add_code(" }", 122)
    ################################################################################ ## compiler/backend/dataplane.c.py:125
    # Table application ## compiler/backend/dataplane.c.py:126

    generated_code += add_code("")
    def unique_stable(items): ## compiler/backend/dataplane.c.py:128
        """Returns only the first occurrence of the items in a list. ## compiler/backend/dataplane.c.py:129
        Equivalent to unique_everseen from Python 3.""" ## compiler/backend/dataplane.c.py:130
        from collections import OrderedDict ## compiler/backend/dataplane.c.py:131
        return list(OrderedDict.fromkeys(items)) ## compiler/backend/dataplane.c.py:132
    for type in unique_stable([comp['type'] for table in hlir16.tables for smem in table.direct_meters + table.direct_counters for comp in smem.components]): ## compiler/backend/dataplane.c.py:135
        generated_code += add_code(' void apply_direct_smem_{}(register_uint32_t* smem, uint32_t value, char* table_name, char* smem_type_name, char* smem_name) {{'.format(type), 135)
        generated_code += add_code('    debug("     : applying apply_direct_smem_{}(register_uint32_t (*smem)[1], uint32_t value, char* table_name, char* smem_type_name, char* smem_name)");'.format(type), 136)
        generated_code += add_code(" }", 137)
    for table in hlir16.tables: ## compiler/backend/dataplane.c.py:141
        lookupfun = {'LPM':'lpm_lookup', 'EXACT':'exact_lookup', 'TERNARY':'ternary_lookup'} ## compiler/backend/dataplane.c.py:142
        generated_code += add_code(' struct apply_result_s {}_apply(STDPARAMS)'.format(table.name), 142)
        generated_code += add_code(" {", 143)
        if hasattr(table, 'key'): ## compiler/backend/dataplane.c.py:145
            generated_code += add_code('     uint8_t* key[{}];'.format(table.key_length_bytes), 145)
            generated_code += add_code('     table_{}_key(pd, (uint8_t*)key);'.format(table.name), 146)
            generated_code += add_code('     dbg_bytes(key, table_config[TABLE_{}].entry.key_size,'.format(table.name), 148)
            generated_code += add_code('               " " T4LIT(????,table) " Table lookup " T4LIT({},table) "/" T4LIT({}) "/" T4LIT(%d) ": %s",'.format(table.name, table.match_type), 149)
            generated_code += add_code('               {},'.format(table.key_length_bytes), 150)
            generated_code += add_code('               {} == 0 ? "" T4LIT((empty key),bytes) "" : "");'.format(table.key_length_bytes), 151)
            generated_code += add_code('     table_entry_{}_t* entry = (table_entry_{}_t*){}(tables[TABLE_{}], (uint8_t*)key);'.format(table.name, table.name, lookupfun[table.match_type], table.name), 153)
            generated_code += add_code("     bool hit = entry != NULL && entry->is_entry_valid != INVALID_TABLE_ENTRY;", 154)
            generated_code += add_code('     debug("   " T4LIT(??,table) " Lookup " T4LIT(%s,success) ": " T4LIT(%s,action) "%s\\n",', 156)
            generated_code += add_code("               hit ? \"hit\" : \"miss\",", 157)
            generated_code += add_code("               entry == NULL ? \"(no action)\" : action_names[entry->action.action_id],", 158)
            generated_code += add_code("               hit ? \"\" : \" (default)\");", 159)
            generated_code += add_code("     if (likely(hit)) {", 161)
            generated_code += add_code("         // applying direct counters and meters", 162)
            for smem in table.direct_meters + table.direct_counters: ## compiler/backend/dataplane.c.py:164
                for comp in smem.components: ## compiler/backend/dataplane.c.py:165
                    value = "pd->parsed_length" if comp['for'] == 'bytes' else "1" ## compiler/backend/dataplane.c.py:166
                    type = comp['type'] ## compiler/backend/dataplane.c.py:167
                    name  = comp['name'] ## compiler/backend/dataplane.c.py:168
                    generated_code += add_code(' extern void apply_{}({}_t*, int, const char*, const char*, const char*);'.format(smem.smem_type, smem.smem_type), 168)
                    generated_code += add_code(' apply_{}(&(global_smem.{}_{}), {}, "{}", "{}", "{}");'.format(smem.smem_type, name, table.name, value, table.name, smem.smem_type, name), 169)
            generated_code += add_code("    }", 170)
        else: ## compiler/backend/dataplane.c.py:172
            action = table.default_action.expression.method.ref.name if hasattr(table, 'default_action') else None ## compiler/backend/dataplane.c.py:173
            if action: ## compiler/backend/dataplane.c.py:175
                generated_code += add_code('    debug(" :::: Lookup on keyless table " T4LIT({},table) ", default action is " T4LIT({},action) "\\n");'.format(table.name, action), 175)
                generated_code += add_code('    table_entry_{}_t resStruct = {{'.format(table.name), 176)
                generated_code += add_code('        .action = {{ action_{} }},'.format(table.default_action.expression.method.ref.name), 177)
                generated_code += add_code("    };", 178)
                generated_code += add_code('    table_entry_{}_t* entry = &resStruct;'.format(table.name), 179)
                generated_code += add_code("    bool hit = true;", 180)
                generated_code += add_code("    bool is_default = false;", 181)
            else: ## compiler/backend/dataplane.c.py:183
                generated_code += add_code('    debug(" :::: Lookup on keyless table " T4LIT({},table) ", " T4LIT(no default action,action) "\\n");'.format(table.name), 183)
                generated_code += add_code('    table_entry_{}_t* entry = (struct {}_action*)0;'.format(table.name, table.name), 184)
                generated_code += add_code("    bool hit = false;", 185)
                generated_code += add_code("    bool is_default = false;", 186)
        # ACTIONS ## compiler/backend/dataplane.c.py:190
        generated_code += add_code("     if (likely(entry != 0)) {", 190)
        generated_code += add_code("       switch (entry->action.action_id) {", 191)
        for action in table.actions: ## compiler/backend/dataplane.c.py:193
            action_name = action.action_object.name ## compiler/backend/dataplane.c.py:194
            if action_name == 'NoAction': ## compiler/backend/dataplane.c.py:195
                continue ## compiler/backend/dataplane.c.py:196
            generated_code += add_code('         case action_{}:'.format(action_name), 196)
            generated_code += add_code('           action_code_{}(SHORT_STDPARAMS_IN, entry->action.{}_params);'.format(action_name, action_name), 197)
            generated_code += add_code("           break;", 198)
        generated_code += add_code("       }", 199)
        generated_code += add_code("     }", 200)
        generated_code += add_code("     struct apply_result_s apply_result = { hit, hit ? entry->action.action_id : -1 };", 202)
        generated_code += add_code("     return apply_result;", 203)
        generated_code += add_code(" }", 204)
    ################################################################################ ## compiler/backend/dataplane.c.py:208

    generated_code += add_code("")
    generated_code += add_code(" void reset_headers(SHORT_STDPARAMS) {", 209)
    for h in hlir16.header_instances: ## compiler/backend/dataplane.c.py:211
        if not h.type('type_ref', lambda t: t.is_metadata): ## compiler/backend/dataplane.c.py:212
            if "tmp" in h.id: ## compiler/backend/dataplane.c.py:213
                generated_code += add_code(" pd->headers['header_instance_t'].pointer = NULL;", 213)
            else: ## compiler/backend/dataplane.c.py:215
                generated_code += add_code(' pd->headers[{}].pointer = NULL;'.format(h.id), 215)
    generated_code += add_code("     // reset metadatas", 217)
    generated_code += add_code("     memset(pd->headers[header_instance_all_metadatas].pointer, 0, header_info(header_instance_all_metadatas).bytewidth * sizeof(uint8_t));", 218)
    generated_code += add_code(" }", 219)

    generated_code += add_code("")
    generated_code += add_code(" void init_headers(SHORT_STDPARAMS) {", 221)
    for h in hlir16.header_instances: ## compiler/backend/dataplane.c.py:223
        if not h.type('type_ref', lambda t: t.is_metadata): ## compiler/backend/dataplane.c.py:224
            if "tmp" in h.id: ## compiler/backend/dataplane.c.py:225
                generated_code += add_code(" pd->headers['header_instance_t'] = (header_descriptor_t)", 225)
                generated_code += add_code(" {", 226)
                generated_code += add_code("     .type =  'header_instance_t',", 227)
                generated_code += add_code("     .length = header_info('header_instance_t').bytewidth,", 228)
                generated_code += add_code("     .pointer = NULL,", 229)
                generated_code += add_code("     .var_width_field_bitwidth = 0,", 230)
                generated_code += add_code(" };", 231)
            else: ## compiler/backend/dataplane.c.py:233
                generated_code += add_code(' pd->headers[{}] = (header_descriptor_t)'.format(h.id), 233)
                generated_code += add_code(" {", 234)
                generated_code += add_code('     .type = {},'.format(h.id), 235)
                generated_code += add_code('     .length = header_info({}).bytewidth,'.format(h.id), 236)
                generated_code += add_code("     .pointer = NULL,", 237)
                generated_code += add_code("     .var_width_field_bitwidth = 0,", 238)
                generated_code += add_code(" };", 239)
    generated_code += add_code("     // init metadatas", 241)
    generated_code += add_code("     pd->headers[header_instance_all_metadatas] = (header_descriptor_t)", 242)
    generated_code += add_code("     {", 243)
    generated_code += add_code("         .type = header_instance_all_metadatas,", 244)
    generated_code += add_code("         .length = header_info(header_instance_all_metadatas).bytewidth,", 245)
    generated_code += add_code("         .pointer = malloc(header_info(header_instance_all_metadatas).bytewidth * sizeof(uint8_t)),", 246)
    generated_code += add_code("         .var_width_field_bitwidth = 0", 247)
    generated_code += add_code("     };", 248)
    generated_code += add_code(" }", 249)

    generated_code += add_code("")
    ################################################################################ ## compiler/backend/dataplane.c.py:252

    generated_code += add_code("")
    def is_keyless_single_action_table(table): ## compiler/backend/dataplane.c.py:254
        return table.key_length_bytes == 0 and len(table.actions) == 2 and table.actions[1].action_object.name.startswith('NoAction') ## compiler/backend/dataplane.c.py:255
    for table in hlir16.tables: ## compiler/backend/dataplane.c.py:257
        if is_keyless_single_action_table(table): ## compiler/backend/dataplane.c.py:258
            generated_code += add_code(' extern void {}_setdefault(struct {}_action);'.format(table.name, table.name), 258)
    generated_code += add_code(" void init_keyless_tables() {", 260)
    for table in hlir16.tables: ## compiler/backend/dataplane.c.py:262
        if is_keyless_single_action_table(table): ## compiler/backend/dataplane.c.py:263
            action = table.actions[0].action_object ## compiler/backend/dataplane.c.py:264
            generated_code += add_code(' struct {}_action {}_a;'.format(table.name, table.name), 264)
            generated_code += add_code(' {}_a.action_id = action_{};'.format(table.name, action.name), 265)
            generated_code += add_code(' {}_setdefault({}_a);'.format(table.name, table.name), 266)
    generated_code += add_code(" }", 267)

    generated_code += add_code("")
    ################################################################################ ## compiler/backend/dataplane.c.py:270

    generated_code += add_code("")
    generated_code += add_code(" void init_dataplane(SHORT_STDPARAMS) {", 271)
    generated_code += add_code("     init_headers(SHORT_STDPARAMS_IN);", 272)
    generated_code += add_code("     reset_headers(SHORT_STDPARAMS_IN);", 273)
    generated_code += add_code("     init_keyless_tables();", 274)

    generated_code += add_code("")
    generated_code += add_code("     uint32_t res32;", 276)
    generated_code += add_code("     MODIFY_INT32_INT32_BITS_PACKET(pd, header_instance_all_metadatas, field_standard_metadata_t_drop, false);", 277)
    generated_code += add_code(" }", 278)

    generated_code += add_code("")
    generated_code += add_code(" void update_packet(packet_descriptor_t* pd) {", 280)
    generated_code += add_code("     uint32_t value32, res32;", 281)
    generated_code += add_code("     (void)value32, (void)res32;", 282)
    for hdr in hlir16.header_instances: ## compiler/backend/dataplane.c.py:284
        if not hasattr(hdr.type, 'type_ref'): ## compiler/backend/dataplane.c.py:285
            continue ## compiler/backend/dataplane.c.py:286
        generated_code += add_code(" ", 287)
        generated_code += add_code(' // updating header instance {}'.format(hdr.name), 288)
        for fld in hdr.type.type_ref.fields: ## compiler/backend/dataplane.c.py:291
            if not fld.preparsed and fld.canonical_type().size <= 32: ## compiler/backend/dataplane.c.py:292
                generated_code += add_code(' if(pd->fields.attr_field_instance_{}_{} == MODIFIED) {{'.format(hdr.name, fld.name), 292)
                generated_code += add_code('     value32 = pd->fields.field_instance_{}_{};'.format(hdr.name, fld.name), 293)
                generated_code += add_code('     MODIFY_INT32_INT32_AUTO_PACKET(pd, header_instance_all_metadatas, field_instance_{}_{}, value32);'.format(hdr.name, fld.name), 294)
                generated_code += add_code('     // set_field((fldT[]){{{{pd, header_instance_{}, field_{}_{}}}}}, 0, value32, {});'.format(hdr.name, hdr.type.type_ref.name, fld.name, fld.canonical_type().size), 295)
                generated_code += add_code(" }", 296)
    generated_code += add_code(" }", 297)

    generated_code += add_code("")
    ################################################################################ ## compiler/backend/dataplane.c.py:300
    # Pipeline ## compiler/backend/dataplane.c.py:301

    generated_code += add_code("")
    class types: ## compiler/backend/dataplane.c.py:303
        def __init__(self, new_type_env): ## compiler/backend/dataplane.c.py:304
            global type_env ## compiler/backend/dataplane.c.py:305
            self.env_vars = set() ## compiler/backend/dataplane.c.py:306
            for v in new_type_env: ## compiler/backend/dataplane.c.py:307
                if v in type_env: ## compiler/backend/dataplane.c.py:308
                    addWarning('adding a type environment', 'variable {} is already bound to type {}'.format(v, type_env[v])) ## compiler/backend/dataplane.c.py:309
                else: ## compiler/backend/dataplane.c.py:310
                    self.env_vars.add(v) ## compiler/backend/dataplane.c.py:311
                    type_env[v] = new_type_env[v] ## compiler/backend/dataplane.c.py:312
        def __enter__(self): ## compiler/backend/dataplane.c.py:314
            global type_env ## compiler/backend/dataplane.c.py:315
            return type_env ## compiler/backend/dataplane.c.py:316
        def __exit__(self, type, value, traceback): ## compiler/backend/dataplane.c.py:318
            global type_env ## compiler/backend/dataplane.c.py:319
            for v in self.env_vars: ## compiler/backend/dataplane.c.py:320
                del type_env[v] ## compiler/backend/dataplane.c.py:321
    # forward declarations for externs ## compiler/backend/dataplane.c.py:323
    for m in hlir16.objects['Method']: ## compiler/backend/dataplane.c.py:324
        # TODO temporary fix for l3-routing-full, this will be computed later on ## compiler/backend/dataplane.c.py:325
        with types({ ## compiler/backend/dataplane.c.py:326
            "T": "struct uint8_buffer_s", ## compiler/backend/dataplane.c.py:327
            "O": "unsigned", ## compiler/backend/dataplane.c.py:328
            "HashAlgorithm": "int", ## compiler/backend/dataplane.c.py:329
        }): ## compiler/backend/dataplane.c.py:330
            t = m.type ## compiler/backend/dataplane.c.py:331
            ret_type = format_type(t.returnType) ## compiler/backend/dataplane.c.py:332
            args = ", ".join([format_expr(arg) for arg in t.parameters.parameters] + ['SHORT_STDPARAMS']) ## compiler/backend/dataplane.c.py:333
            generated_code += add_code(' extern {} {}({});'.format(ret_type, m.name, args), 334)
    for ctl in p4_ctls: ## compiler/backend/dataplane.c.py:337
        generated_code += add_code(' void control_{}(STDPARAMS)'.format(ctl.name), 337)
        generated_code += add_code(" {", 338)
        generated_code += add_code('     debug("Entering control " T4LIT({},control) "...\\n");'.format(ctl.name), 339)
        generated_code += add_code("     uint32_t value32, res32;", 340)
        generated_code += add_code("     (void)value32, (void)res32;", 341)
        generated_code += add_code('     control_locals_{}_t local_vars_struct;'.format(ctl.name), 342)
        generated_code += add_code('     control_locals_{}_t* local_vars = &local_vars_struct;'.format(ctl.name), 343)
        generated_code += add_code("     pd->control_locals = (void*) local_vars;", 344)
        generated_code += str( format_statement(ctl.body, ctl)) ## compiler/backend/dataplane.c.py:345
        generated_code += add_code(" }", 346)
    generated_code += add_code(" void process_packet(STDPARAMS)", 348)
    generated_code += add_code(" {", 349)
    it=0 ## compiler/backend/dataplane.c.py:351
    for ctl in p4_ctls: ## compiler/backend/dataplane.c.py:352
        generated_code += add_code(' control_{}(STDPARAMS_IN);'.format(ctl.name), 352)
        if hlir16.p4_model == 'V1Switch' and it==1: ## compiler/backend/dataplane.c.py:354
            generated_code += add_code(" transfer_to_egress(pd);", 354)
        it = it+1; ## compiler/backend/dataplane.c.py:356
        if ctl.name == 'egress': ## compiler/backend/dataplane.c.py:357
            generated_code += add_code(" // TODO temporarily disabled", 357)
            generated_code += add_code(" // update_packet(pd); // we need to update the packet prior to calculating the new checksum", 358)
    generated_code += add_code(" }", 359)

    generated_code += add_code("")
    ################################################################################ ## compiler/backend/dataplane.c.py:362

    generated_code += add_code("")
    longest_hdr_name_len =max({len(h.name) for h in hlir16.header_instances if hasattr(h.type._type_ref, 'is_metadata') if not h.type._type_ref.is_metadata }) ## compiler/backend/dataplane.c.py:364

    generated_code += add_code("")
    pkt_name_indent = " " * longest_hdr_name_len ## compiler/backend/dataplane.c.py:366

    generated_code += add_code("")
    generated_code += add_code(" void store_headers_for_emit(STDPARAMS)", 367)
    generated_code += add_code(" {", 368)
    generated_code += add_code('     debug("   :: Preparing " T4LIT(%d) " header instances for storage...\\n", pd->emit_hdrinst_count);', 369)

    generated_code += add_code("")
    generated_code += add_code("     pd->emit_headers_length = 0;", 371)
    generated_code += add_code("     for (int i = 0; i < pd->emit_hdrinst_count; ++i) {", 372)
    generated_code += add_code("         header_descriptor_t hdr = pd->headers[pd->header_reorder[i]];", 373)

    generated_code += add_code("")
    generated_code += add_code("", 375)
    generated_code += add_code("         #if PPK_EMIT != 1", 376)
    generated_code += add_code("             if (unlikely(hdr.pointer == NULL)) {", 377)
    generated_code += add_code('                 debug("        : " T4LIT(#%d) " " T4LIT(%{}s,header) "/" T4LIT(%02d) " = " T4LIT(skipping invalid header,warning) "\\n", pd->header_reorder[i] + 1, hdr.name, hdr.length);'.format(longest_hdr_name_len), 378)
    generated_code += add_code("                 continue;", 379)
    generated_code += add_code("             }", 380)
    generated_code += add_code("         #endif", 381)

    generated_code += add_code("")
    generated_code += add_code("         if (likely(hdr.was_enabled_at_initial_parse)) {", 383)
    generated_code += add_code('             dbg_bytes(hdr.pointer, hdr.length, "        : " T4LIT(#%d) " " T4LIT(%{}s,header) "/" T4LIT(%02d) " = %s", pd->header_reorder[i] + 1, hdr.name, hdr.length, hdr.pointer == NULL ? T4LIT((invalid),warning) " " : "");'.format(longest_hdr_name_len), 384)
    generated_code += add_code("             memcpy(pd->header_tmp_storage + header_instance_infos[hdr.type].byte_offset, hdr.pointer, hdr.length);", 385)
    generated_code += add_code("         } else {", 386)
    generated_code += add_code('             debug("        : " T4LIT(#%d) " " T4LIT(%{}s,header) "/" T4LIT(%02d) " was created in-place (not present at ingress)\\n", pd->header_reorder[i] + 1, hdr.name, hdr.length);'.format(longest_hdr_name_len), 387)
    generated_code += add_code("         }", 388)
    generated_code += add_code("", 389)
    generated_code += add_code("         pd->emit_headers_length += hdr.length;", 390)
    generated_code += add_code("     }", 391)
    generated_code += add_code(" }", 392)

    generated_code += add_code("")
    generated_code += add_code(" void resize_packet_on_emit(STDPARAMS)", 394)
    generated_code += add_code(" {", 395)
    generated_code += add_code("     if (likely(pd->emit_headers_length == pd->parsed_length)) {", 396)
    generated_code += add_code("         debug(\" \" T4LIT(::::,status) \" Skipping packet resizing: no change in total packet header length\\n\");", 397)
    generated_code += add_code("         return;", 398)
    generated_code += add_code("     }", 399)
    generated_code += add_code("", 400)
    generated_code += add_code("     if (likely(pd->emit_headers_length > pd->parsed_length)) {", 401)
    generated_code += add_code("         int len_change = pd->emit_headers_length - pd->parsed_length;", 402)
    generated_code += add_code('         debug("   " T4LIT(::,status) " Adding   " T4LIT(%02d) " bytes %{}s   : (header: from " T4LIT(%d) " bytes to " T4LIT(%d) " bytes)\\n", len_change, "to packet", pd->parsed_length, pd->emit_headers_length);'.format(longest_hdr_name_len), 403)
    generated_code += add_code("         char* new_ptr = rte_pktmbuf_prepend(pd->wrapper, len_change);", 404)
    generated_code += add_code("         if (unlikely(new_ptr == 0)) {", 405)
    generated_code += add_code('             rte_exit(1, "Could not reserve necessary headroom (" T4LIT(%d) " additional bytes)", len_change);', 406)
    generated_code += add_code("         }", 407)
    generated_code += add_code("         pd->data = (packet_data_t*)new_ptr;", 408)
    generated_code += add_code("     } else {", 409)
    generated_code += add_code("         int len_change = pd->parsed_length - pd->emit_headers_length;", 410)
    generated_code += add_code('         debug("   " T4LIT(::,status) " Removing " T4LIT(%02d) " bytes %{}s  : (header: from " T4LIT(%d) " bytes to " T4LIT(%d) " bytes)\\n", len_change, "from packet", pd->parsed_length, pd->emit_headers_length);'.format(longest_hdr_name_len), 411)
    generated_code += add_code("         char* new_ptr = rte_pktmbuf_adj(pd->wrapper, len_change);", 412)
    generated_code += add_code("         pd->data = (packet_data_t*)new_ptr;", 413)
    generated_code += add_code("     }", 414)
    generated_code += add_code("     pd->wrapper->pkt_len = pd->emit_headers_length + pd->payload_length;", 415)
    generated_code += add_code(" }", 416)

    generated_code += add_code("")
    generated_code += add_code(" // if (some of) the emitted headers are one after another, this function copies them in one go", 418)
    generated_code += add_code(" void copy_emit_contents(STDPARAMS)", 419)
    generated_code += add_code(" {", 420)
    generated_code += add_code("     debug(\"   :: Putting together packet\\n\");", 421)
    generated_code += add_code("     uint8_t* dst_start = rte_pktmbuf_mtod(pd->wrapper, uint8_t*);", 422)
    generated_code += add_code("     uint8_t* dst = dst_start;", 423)
    generated_code += add_code("     //TODO by IAN", 424)
    generated_code += add_code("       struct vlan_tag", 425)
    generated_code += add_code("    {  ", 426)
    generated_code += add_code("         uint16_t type;", 427)
    generated_code += add_code("         uint16_t vid:12;", 428)
    generated_code += add_code("         uint8_t cfi:1;", 429)
    generated_code += add_code("         uint8_t pri:3;", 430)
    generated_code += add_code("     }vlan;", 431)
    generated_code += add_code("     for (int idx = 0; idx < pd->emit_hdrinst_count; ) {", 432)
    generated_code += add_code("           if (idx == 1 ){", 433)
    generated_code += add_code("             int egress_port = extract_egress_port(pd);", 434)
    generated_code += add_code("             vlan.pri = 0;", 435)
    generated_code += add_code("             vlan.cfi = 0;", 436)
    generated_code += add_code("             vlan.vid = (0xfff & egress_port) + (GET_INT32_AUTO_PACKET(pd, header_instance_all_metadatas, ingress_port_field()) - 63);", 437)
    generated_code += add_code("             vlan.type = 0x0800;", 438)
    generated_code += add_code("              uint32_t vlan_of = *(uint32_t *)&vlan;", 439)
    generated_code += add_code("              uint32_t vlan1 = rte_cpu_to_be_32(vlan_of);", 440)
    generated_code += add_code("             memcpy(dst, &vlan1, sizeof(vlan));", 441)
    generated_code += add_code("             dst += 4;", 442)
    generated_code += add_code("        }", 443)
    generated_code += add_code("             if (pd->headers[pd->header_reorder[idx]].pointer == NULL){", 444)
    generated_code += add_code("             idx++;", 445)
    generated_code += add_code("             continue;", 446)
    generated_code += add_code("         }", 447)
    generated_code += add_code("         #ifdef PPK_DEBUG", 448)
    generated_code += add_code("             char header_names_txt[1024];", 449)
    generated_code += add_code("             char* header_names_ptr = header_names_txt;", 450)
    generated_code += add_code("         #endif", 451)
    generated_code += add_code("         header_descriptor_t hdr = pd->headers[pd->header_reorder[idx]];", 452)
    generated_code += add_code("         uint8_t* copy_start     = hdr.pointer;", 453)
    generated_code += add_code("         int copy_start_idx      = idx;", 454)
    generated_code += add_code("         int copy_length         = hdr.length;", 455)
    generated_code += add_code("         int count               = 1;", 456)
    generated_code += add_code("         #ifdef PPK_DEBUG", 457)
    generated_code += add_code("             header_names_ptr += sprintf(header_names_ptr, \" \" T4LIT(%s,header), hdr.name);", 458)
    generated_code += add_code("         #endif", 459)
    generated_code += add_code("         ++idx;", 460)
    generated_code += add_code("         while (idx < pd->emit_hdrinst_count && pd->headers[pd->header_reorder[idx]].pointer == hdr.pointer + hdr.length) {", 461)
    generated_code += add_code("             ++count;", 462)
    generated_code += add_code("             hdr = pd->headers[pd->header_reorder[idx]];", 463)
    generated_code += add_code("             copy_length += hdr.length;", 464)
    generated_code += add_code("             ++idx;", 465)
    generated_code += add_code("             #ifdef PPK_DEBUG", 466)
    generated_code += add_code("                 header_names_ptr += sprintf(header_names_ptr, \" \" T4LIT(%s,header), hdr.name);", 467)
    generated_code += add_code("             #endif", 468)
    generated_code += add_code("         }", 469)
    generated_code += add_code("         dbg_bytes(copy_start, copy_length, \"    : Copying \" T4LIT(%d) \" %s to byte \" T4LIT(#%ld) \" of egress header, \" T4LIT(%d) \" bytes: %s: \", count, count == 1 ? \"header\" : \"adjacent headers\", dst - dst_start, copy_length, header_names_txt);", 470)
    generated_code += add_code("         memcpy(dst, copy_start, copy_length);", 471)
    generated_code += add_code("         dst += copy_length;", 472)
    generated_code += add_code("     }", 473)
    generated_code += add_code(" }", 474)

    generated_code += add_code("")
    generated_code += add_code(" void emit_packet(STDPARAMS)", 476)
    generated_code += add_code(" {", 477)
    generated_code += add_code("     if (unlikely(pd->is_emit_reordering)) {", 478)
    generated_code += add_code("         if (unlikely(GET_INT32_AUTO_PACKET(pd, header_instance_all_metadatas, field_standard_metadata_t_drop))) {", 479)
    generated_code += add_code("             debug(\" \" T4LIT(::::,status) \" Skipping pre-emit processing: packet is \" T4LIT(dropped,status) \"\\n\");", 480)
    generated_code += add_code("             return;", 481)
    generated_code += add_code("         }", 482)
    generated_code += add_code("         debug(\" :::: Pre-emit reordering\\n\");", 483)
    generated_code += add_code("         store_headers_for_emit(STDPARAMS_IN);", 484)
    generated_code += add_code("         resize_packet_on_emit(STDPARAMS_IN);", 485)
    generated_code += add_code("         copy_emit_contents(STDPARAMS_IN);", 486)
    generated_code += add_code("     } else {", 487)
    generated_code += add_code("         debug(\" \" T4LIT(::::,status) \" Skipping pre-emit processing: no change in packet header structure\\n\");", 488)
    generated_code += add_code("     }", 489)
    generated_code += add_code(" }", 490)

    generated_code += add_code("")
    generated_code += add_code(" void handle_packet(STDPARAMS, uint32_t portid)", 492)
    generated_code += add_code(" {", 493)
    generated_code += add_code("     int value32;", 494)
    generated_code += add_code("     int res32;", 495)
    generated_code += add_code("", 496)
    generated_code += add_code("     reset_headers(SHORT_STDPARAMS_IN);", 497)
    generated_code += add_code("     set_handle_packet_metadata(pd, portid);", 498)
    generated_code += add_code("", 499)
    generated_code += add_code('     dbg_bytes(pd->data, packet_length(pd), "Handling packet (port " T4LIT(%d,port) ", " T4LIT(%02d) " bytes)  : ", extract_ingress_port(pd), packet_length(pd));', 500)
    generated_code += add_code("", 501)
    generated_code += add_code("     pd->parsed_length = 0;", 502)
    generated_code += add_code("     parse_packet(STDPARAMS_IN);", 503)
    generated_code += add_code("", 504)
    generated_code += add_code("     emit_addr = pd->data;", 505)
    generated_code += add_code("     pd->emit_hdrinst_count = 0;", 506)
    generated_code += add_code("     pd->is_emit_reordering = false;", 507)
    generated_code += add_code("", 508)
    generated_code += add_code("     process_packet(STDPARAMS_IN);", 509)
    generated_code += add_code("", 510)
    generated_code += add_code("     emit_packet(STDPARAMS_IN);", 511)
    generated_code += add_code(" }", 512)

